﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using BattleCity.GameLogic;
using Microsoft.FSharp.Collections;

namespace BattleCity.GameLogic.Xml
{
    public enum TankType
    {
        Player,
        Blue,
        Silver,
        Black
    }

    public enum WeaponType
    {
        SingleBullet,
        DoubleBullet,
        RenforcedBullet
    }

    public enum Bonus
    {
        WeaponUp,
        Nuclear,
        Life,
        Shield,
        None
    }

    public enum PlayerState
    {
        Spawning,
        Destroyed,
        Playing
    }

    public struct Tank
    {
        public Microsoft.Xna.Framework.Vector2 direction;
        public Microsoft.Xna.Framework.Vector2 position;
        public float velocity;
        public float wheelRoolTheta;
        public TankType tankType;
        public bool isStealth;
        public Bonus bonus;
        public WeaponType weapon;
    }

    public enum BlockType
    {
        Empty,
        Ceramic,
        Steel,
        Stealth,
        Space
    }

    public struct SerializableTuple<T1, T2>
    {
        public T1 Item1;
        public T2 Item2;
    }

    public struct SerializableTuple<T1, T2, T3>
    {
        public T1 Item1;
        public T2 Item2;
        public T3 Item3;
    }

    public class SerializableGameState
    {
        public Tank playerTank;
        public PlayerState playerState;
        public float playerTransitionClock;
        public int playerLives;

        public List<Tank> enemiesList;
        public List<SerializableTuple<Tank, float>> destroyedEnemiesList;
        public List<SerializableTuple<Tank, float>> spawnedEnemiesList;

        public int generatedEnemies;
        public int destroyedEnemies;

        public int levelNumber;
        public int completedLevels;
       

        public SerializableTuple<BlockType, bool[]>[] blockGrid;

        public List<SerializableTuple<Bonus, Microsoft.Xna.Framework.Vector2, float>> bonusList;

        public SerializableGameState()
        {
            playerTank = new Tank();
            enemiesList = new List<Tank>();
            spawnedEnemiesList = new List<SerializableTuple<Tank, float>>();
            destroyedEnemiesList = new List<SerializableTuple<Tank, float>>();
            bonusList = new List<SerializableTuple<Bonus, Microsoft.Xna.Framework.Vector2, float>>();
        }

        public void setSerializableGameState(int levelNumber)
        {
            this.levelNumber = levelNumber;
            this.completedLevels = GameState.gameState.CompletedLevels.Value;

            playerTank = new Tank();
            enemiesList = new List<Tank>();
            spawnedEnemiesList = new List<SerializableTuple<Tank, float>>();
            destroyedEnemiesList = new List<SerializableTuple<Tank, float>>();
            blockGrid = new SerializableTuple<BlockType, bool[]>[13 * 13];
            bonusList = new List<SerializableTuple<Bonus, Microsoft.Xna.Framework.Vector2, float>>();

            //PLAYER TANK
            playerLives = GameState.gameState.PlayerLives.Value;

            playerState = PlayerState.Playing;
            if (GameState.gameState.PlayerState.Value.IsDestroyed) playerState = PlayerState.Destroyed;
            if (GameState.gameState.PlayerState.Value.IsSpawning) playerState = PlayerState.Spawning;
            playerTransitionClock = (float)GameState.gameState.PlayerTransitionClock.Value;

            playerTank.direction = GameState.gameState.PlayerTank.Value.Direction.xnaVector2;
            playerTank.position = GameState.gameState.PlayerTank.Value.Position.xnaVector2;
            playerTank.velocity = (float)GameState.gameState.PlayerTank.Value.Velocity;
            playerTank.wheelRoolTheta = (float)GameState.gameState.PlayerTank.Value.WheelRollTheta;
            playerTank.tankType = TankType.Player;
            playerTank.isStealth = GameState.gameState.PlayerTank.Value.IsStealth;
            playerTank.bonus = Bonus.None;

            if (GameState.gameState.PlayerTank.Value.Weapon.IsDoubleBullet) playerTank.weapon = WeaponType.DoubleBullet;
            if (GameState.gameState.PlayerTank.Value.Weapon.IsSingleBullet) playerTank.weapon = WeaponType.SingleBullet;
            if (GameState.gameState.PlayerTank.Value.Weapon.IsRenforcedBullet) playerTank.weapon = WeaponType.RenforcedBullet;

            //ENEMIES TANKS
            generatedEnemies = GameState.gameState.GeneratedEnemies.Value;
            destroyedEnemies = GameState.gameState.DestroyedEnemies.Value;

            foreach (Casanova.Variable<Types.Tank> enTank in GameState.gameState.EnemiesList.Value)
            {
                Tank serializableTank = new Tank();

                serializableTank.direction = enTank.Value.Direction.xnaVector2;
                serializableTank.position = enTank.Value.Position.xnaVector2;
                serializableTank.velocity = (float)enTank.Value.Velocity;
                serializableTank.wheelRoolTheta = (float)enTank.Value.WheelRollTheta;

                Types.EnemyType enType = Types.getEnemyType(enTank.Value.TankType);
                serializableTank.tankType = TankType.Silver;
                if (enType.IsBlack) serializableTank.tankType = TankType.Black;
                if (enType.IsBlue) serializableTank.tankType = TankType.Blue;


                serializableTank.isStealth = enTank.Value.IsStealth;

                if (enTank.Value.Bonus.IsLife) serializableTank.bonus = Bonus.Life;
                if (enTank.Value.Bonus.IsNone) serializableTank.bonus = Bonus.None;
                if (enTank.Value.Bonus.IsNuclear) serializableTank.bonus = Bonus.Nuclear;
                if (enTank.Value.Bonus.IsShield) serializableTank.bonus = Bonus.Shield;
                if (enTank.Value.Bonus.IsWeaponUp) serializableTank.bonus = Bonus.WeaponUp;

                if (enTank.Value.Weapon.IsDoubleBullet) serializableTank.weapon = WeaponType.DoubleBullet;
                if (enTank.Value.Weapon.IsSingleBullet) serializableTank.weapon = WeaponType.SingleBullet;
                if (enTank.Value.Weapon.IsRenforcedBullet) serializableTank.weapon = WeaponType.RenforcedBullet;

                enemiesList.Add(serializableTank);
            }

            foreach (Tuple<Types.Tank, double> enTank in GameState.gameState.SpawnedEnemiesList.Value)
            {
                Tank serializableTank = new Tank();

                serializableTank.direction = enTank.Item1.Direction.xnaVector2;
                serializableTank.position = enTank.Item1.Position.xnaVector2;
                serializableTank.velocity = (float)enTank.Item1.Velocity;
                serializableTank.wheelRoolTheta = (float)enTank.Item1.WheelRollTheta;


                Types.EnemyType enType = Types.getEnemyType(enTank.Item1.TankType);
                serializableTank.tankType = TankType.Silver;
                if (enType.IsBlack) serializableTank.tankType = TankType.Black;
                if (enType.IsBlue) serializableTank.tankType = TankType.Blue;

                serializableTank.isStealth = enTank.Item1.IsStealth;

                if (enTank.Item1.Bonus.IsLife) serializableTank.bonus = Bonus.Life;
                if (enTank.Item1.Bonus.IsNone) serializableTank.bonus = Bonus.None;
                if (enTank.Item1.Bonus.IsNuclear) serializableTank.bonus = Bonus.Nuclear;
                if (enTank.Item1.Bonus.IsShield) serializableTank.bonus = Bonus.Shield;
                if (enTank.Item1.Bonus.IsWeaponUp) serializableTank.bonus = Bonus.WeaponUp;

                if (enTank.Item1.Weapon.IsDoubleBullet) serializableTank.weapon = WeaponType.DoubleBullet;
                if (enTank.Item1.Weapon.IsSingleBullet) serializableTank.weapon = WeaponType.SingleBullet;
                if (enTank.Item1.Weapon.IsRenforcedBullet) serializableTank.weapon = WeaponType.RenforcedBullet;

                SerializableTuple<Tank, float> tuple;
                tuple.Item1 = serializableTank;
                tuple.Item2 = (float)enTank.Item2;
                spawnedEnemiesList.Add(tuple);
            }

            foreach (Tuple<Types.Tank, double> enTank in GameState.gameState.DestroyedEnemiesList.Value)
            {
                Tank serializableTank = new Tank();

                serializableTank.direction = enTank.Item1.Direction.xnaVector2;
                serializableTank.position = enTank.Item1.Position.xnaVector2;
                serializableTank.velocity = (float)enTank.Item1.Velocity;
                serializableTank.wheelRoolTheta = (float)enTank.Item1.WheelRollTheta;


                Types.EnemyType enType = Types.getEnemyType(enTank.Item1.TankType);
                serializableTank.tankType = TankType.Silver;
                if (enType.IsBlack) serializableTank.tankType = TankType.Black;
                if (enType.IsBlue) serializableTank.tankType = TankType.Blue;

                serializableTank.isStealth = enTank.Item1.IsStealth;

                if (enTank.Item1.Bonus.IsLife) serializableTank.bonus = Bonus.Life;
                if (enTank.Item1.Bonus.IsNone) serializableTank.bonus = Bonus.None;
                if (enTank.Item1.Bonus.IsNuclear) serializableTank.bonus = Bonus.Nuclear;
                if (enTank.Item1.Bonus.IsShield) serializableTank.bonus = Bonus.Shield;
                if (enTank.Item1.Bonus.IsWeaponUp) serializableTank.bonus = Bonus.WeaponUp;

                if (enTank.Item1.Weapon.IsDoubleBullet) serializableTank.weapon = WeaponType.DoubleBullet;
                if (enTank.Item1.Weapon.IsSingleBullet) serializableTank.weapon = WeaponType.SingleBullet;
                if (enTank.Item1.Weapon.IsRenforcedBullet) serializableTank.weapon = WeaponType.RenforcedBullet;

                SerializableTuple<Tank, float> tuple;
                tuple.Item1 = serializableTank;
                tuple.Item2 = (float)enTank.Item2;
                spawnedEnemiesList.Add(tuple);
                destroyedEnemiesList.Add(tuple);
            }

            //BLOCKS
            Casanova.commit_variable_updates();
            for (int i = 0; i < 13; ++i)
            {
                for(int j = 0; j < 13; ++j)
                {
                    var block = GameState.gameState.BlockGrid[i, j];
                   
                    BlockType blockType = BlockType.Empty;

                    int brickCount = 0;
                    if (block.makeUp.IsCeramicBrick)
                    {
                        blockType = BlockType.Ceramic;
                        brickCount = 4;
                    }
                    if (block.makeUp.IsSteelBrick)
                    {
                        blockType = BlockType.Steel;
                        brickCount = 2;
                    }

                    if (block.makeUp.IsSpace) blockType = BlockType.Space;
                    if (block.makeUp.IsStealth) blockType = BlockType.Stealth;

                    blockGrid[i * 13 + j].Item1 = blockType;

                    if (brickCount > 0)
                    {
                        blockGrid[i * 13 + j].Item2 = new bool[brickCount * brickCount];
                        for (int c = 0; c < brickCount; ++c)
                        {
                            for (int k = 0; k < brickCount; ++k)
                            {
                                blockGrid[i * 13 + j].Item2[c * brickCount + k] = Types.getBricks(block.makeUp).Value[c, k];
                            }
                        }
                    }
                    else
                    {
                        blockGrid[i * 13 + j].Item2 = new bool[1];
                    }

                }
            }

            foreach (Tuple<Types.Bonus,FMath.Vector2,double> bonus in GameState.gameState.BonusList.Value)
            {
                Bonus bonusType = Bonus.None;
                if(bonus.Item1.IsLife) bonusType = Bonus.Life;
                if(bonus.Item1.IsNuclear) bonusType = Bonus.Nuclear;
                if(bonus.Item1.IsShield) bonusType = Bonus.Shield;
                if(bonus.Item1.IsWeaponUp) bonusType = Bonus.WeaponUp;

                SerializableTuple<Bonus, Microsoft.Xna.Framework.Vector2, float> serializableBonus;
                serializableBonus.Item1 = bonusType;
                serializableBonus.Item2 = bonus.Item2.xnaVector2;
                serializableBonus.Item3 = (float)bonus.Item3;

                bonusList.Add(serializableBonus);
            }

            Casanova.commit_variable_updates();
        }

        public static void loadTankList(SerializableTuple<TankType, Bonus>[] tankList)
        {
            List<System.Tuple<Types.EnemyType, Types.Bonus>> enemyList = new List<Tuple<Types.EnemyType,Types.Bonus>>();
            
            foreach(SerializableTuple<TankType, Bonus> element in tankList)
            {
                Types.EnemyType enemyType;
                Types.Bonus bonusType;

                switch (element.Item1)
                {
                    case TankType.Black:
                        enemyType = Types.EnemyType.Black;
                        break;
                    case TankType.Blue:
                        enemyType = Types.EnemyType.Blue;
                        break;
                    default:
                        enemyType = Types.EnemyType.Silver;
                        break;
                }

                switch (element.Item2)
                {
                    case Bonus.Life:
                        bonusType = Types.Bonus.Life;
                        break;
                    case Bonus.Shield:
                        bonusType = Types.Bonus.Shield;
                        break;
                    case Bonus.Nuclear:
                        bonusType = Types.Bonus.Nuclear;
                        break;
                    case Bonus.WeaponUp:
                        bonusType = Types.Bonus.WeaponUp;
                        break;
                    default:
                        bonusType = Types.Bonus.None;
                        break;
                }

                enemyList.Add(new Tuple<Types.EnemyType, Types.Bonus>(enemyType, bonusType));
            }

            GameState.loadEnemiesList(enemyList);
        }

        public static void loadLevel(SerializableTuple<BlockType, bool[]>[] blockGrid, bool nextLevel)
        {
            Types.BlockMakeUp[,] blockMap = new Types.BlockMakeUp[13, 13];
            for (int i = 0; i < 13; ++i)
            {
                for (int j = 0; j < 13; ++j)
                {
                    Types.BlockMakeUp makeUp;
                    switch (blockGrid[i * 13 + j].Item1)
                    {
                        case BlockType.Steel:
                            bool[,] steelBrickArray = new bool[2, 2];
                            for (int c = 0; c < 2; ++c)
                            {
                                for (int k = 0; k < 2; ++k)
                                {
                                    steelBrickArray[c, k] = blockGrid[i * 13 + j].Item2[c * 2 + k];
                                }
                            }
                            makeUp = Types.BlockMakeUp.NewSteelBrick(new Casanova.Variable<bool[,]>(steelBrickArray, steelBrickArray));
                            break;
                        case BlockType.Ceramic:
                            bool[,] ceramicBrickArray = new bool[4, 4];
                            for (int c = 0; c < 4; ++c)
                            {
                                for (int k = 0; k < 4; ++k)
                                {
                                    ceramicBrickArray[c, k] = blockGrid[i * 13 + j].Item2[c * 4 + k];
                                }
                            }
                            makeUp = Types.BlockMakeUp.NewCeramicBrick(new Casanova.Variable<bool[,]>(ceramicBrickArray, ceramicBrickArray));
                            break;
                        case BlockType.Space:
                            makeUp = Types.BlockMakeUp.Space;
                            break;
                        case BlockType.Stealth:
                            makeUp = Types.BlockMakeUp.Stealth;
                            break;
                        default:
                            makeUp = Types.BlockMakeUp.Empty;
                            break;
                    }
                    blockMap[i, j] = makeUp;
                }
            }

            Types.Tank playerTank = GameState.playerTank;
            int lives = 3;
            int completedLevels = 0;

            if (nextLevel)
            {
                playerTank = GameState.CreateTankState(GameState.playerTank.Direction,
                                                           GameState.playerTank.Position,
                                                           GameState.playerTank.Velocity,
                                                           GameState.playerTank.WheelRollTheta,
                                                           GameState.playerTank.TankType,
                                                           false,
                                                           GameState.playerTank.Bonus,
                                                           GameState.gameState.PlayerTank.Value.Weapon);

                lives = GameState.gameState.PlayerLives.Value;
                completedLevels = GameState.gameState.CompletedLevels.Value;

            }



            GameState.gameState = GameState.loadGameState(playerTank,
                                                          lives,
                                                          completedLevels,
                                                          Types.PlayerState.Spawning,
                                                          0.0d,
                                                          0,
                                                          0,
                                                          new List<Tuple<Types.Tank, double>>(),
                                                          new List<Tuple<Types.Tank, double>>(),
                                                          new List<Types.Tank>(),
                                                          new List<Tuple<Types.Bonus,FMath.Vector2,double>>(),
                                                          blockMap);
        }

        public void loadSerializedGameState()
        {

            //Caricamento dello stato del giocatore
            Types.WeaponType playerWeapon = Types.WeaponType.SingleBullet;
            switch(this.playerTank.weapon)
            {
                case WeaponType.DoubleBullet:
                    playerWeapon = Types.WeaponType.DoubleBullet;
                    break;
                case WeaponType.RenforcedBullet:
                    playerWeapon = Types.WeaponType.RenforcedBullet;
                    break;
            }

            Types.PlayerState plState = Types.PlayerState.Playing;
            switch (this.playerState)
            {
                case PlayerState.Spawning:
                    plState = Types.PlayerState.Spawning;
                    break;
                case PlayerState.Destroyed:
                    plState = Types.PlayerState.Destroyed;
                    break;
            }

            Types.Tank playerTank = GameState.CreateTankState(new FMath.Vector2(this.playerTank.direction.X, this.playerTank.direction.Y),
                                                               new FMath.Vector2(this.playerTank.position.X, this.playerTank.position.Y),
                                                               this.playerTank.velocity,
                                                               this.playerTank.wheelRoolTheta,
                                                               Types.TankType.PlayerTank,
                                                               this.playerTank.isStealth,
                                                               Types.Bonus.None,
                                                               playerWeapon);


            //Caricamento dello stato dei nemici

            List<Types.Tank> enList = new List<Types.Tank>();
            List<Tuple<Types.Tank, double>> enDestroyedList = new List<Tuple<Types.Tank, double>>();
            List<Tuple<Types.Tank, double>> enSpawnedList = new List<Tuple<Types.Tank, double>>();
            List<Tuple<Types.Bonus, FMath.Vector2, double>> bnList = new List<Tuple<Types.Bonus, FMath.Vector2, double>>();

            #region alive enemies
            foreach (Tank enTank in enemiesList)
            {
                Types.EnemyType enType = Types.EnemyType.Silver;
                switch (enTank.tankType)
                {
                    case TankType.Black:
                        enType = Types.EnemyType.Black;
                        break;
                    case TankType.Blue:
                        enType = Types.EnemyType.Blue;
                        break;
                }

                Types.Bonus enBonus = Types.Bonus.None;
                switch(enTank.bonus)
                {
                    case Bonus.Life:
                        enBonus = Types.Bonus.Life;
                        break;
                    case Bonus.Nuclear:
                        enBonus = Types.Bonus.Nuclear;
                        break;
                    case Bonus.Shield:
                        enBonus = Types.Bonus.Shield;
                        break;
                    case Bonus.WeaponUp:
                        enBonus = Types.Bonus.WeaponUp;
                        break;
                }

                Types.WeaponType enWeapon = Types.WeaponType.SingleBullet;
                switch (enTank.weapon)
                {
                    case WeaponType.DoubleBullet:
                        playerWeapon = Types.WeaponType.DoubleBullet;
                        break;
          
                }

                enList.Add(GameState.CreateTankState(new FMath.Vector2(enTank.direction.X, enTank.direction.Y),
                                                               new FMath.Vector2(enTank.position.X, enTank.position.Y),
                                                               enTank.velocity,
                                                               enTank.wheelRoolTheta,
                                                               Types.createEnemyType(enType),
                                                               enTank.isStealth,
                                                               enBonus,
                                                               enWeapon));
            }
            #endregion

            #region destroyed enemies
            foreach (SerializableTuple<Tank, float> enTank in destroyedEnemiesList)
            {
                Types.EnemyType enType = Types.EnemyType.Silver;
                switch (enTank.Item1.tankType)
                {
                    case TankType.Black:
                        enType = Types.EnemyType.Black;
                        break;
                    case TankType.Blue:
                        enType = Types.EnemyType.Blue;
                        break;
                }

                Types.Bonus enBonus = Types.Bonus.None;
                switch (enTank.Item1.bonus)
                {
                    case Bonus.Life:
                        enBonus = Types.Bonus.Life;
                        break;
                    case Bonus.Nuclear:
                        enBonus = Types.Bonus.Nuclear;
                        break;
                    case Bonus.Shield:
                        enBonus = Types.Bonus.Shield;
                        break;
                    case Bonus.WeaponUp:
                        enBonus = Types.Bonus.WeaponUp;
                        break;
                }

                Types.WeaponType enWeapon = Types.WeaponType.SingleBullet;
                switch (enTank.Item1.weapon)
                {
                    case WeaponType.DoubleBullet:
                        playerWeapon = Types.WeaponType.DoubleBullet;
                        break;

                }

                enDestroyedList.Add(new Tuple<Types.Tank,double>(GameState.CreateTankState(new FMath.Vector2(enTank.Item1.direction.X, enTank.Item1.direction.Y),
                                                                                           new FMath.Vector2(enTank.Item1.position.X, enTank.Item1.position.Y),
                                                                                           enTank.Item1.velocity,
                                                                                           enTank.Item1.wheelRoolTheta,
                                                                                           Types.createEnemyType(enType),
                                                                                           enTank.Item1.isStealth,
                                                                                           enBonus,
                                                                                           enWeapon),enTank.Item2));
            }
            #endregion

            #region spawned enemies
            foreach (SerializableTuple<Tank, float> enTank in spawnedEnemiesList)
            {
                Types.EnemyType enType = Types.EnemyType.Silver;
                switch (enTank.Item1.tankType)
                {
                    case TankType.Black:
                        enType = Types.EnemyType.Black;
                        break;
                    case TankType.Blue:
                        enType = Types.EnemyType.Blue;
                        break;
                }

                Types.Bonus enBonus = Types.Bonus.None;
                switch (enTank.Item1.bonus)
                {
                    case Bonus.Life:
                        enBonus = Types.Bonus.Life;
                        break;
                    case Bonus.Nuclear:
                        enBonus = Types.Bonus.Nuclear;
                        break;
                    case Bonus.Shield:
                        enBonus = Types.Bonus.Shield;
                        break;
                    case Bonus.WeaponUp:
                        enBonus = Types.Bonus.WeaponUp;
                        break;
                }

                Types.WeaponType enWeapon = Types.WeaponType.SingleBullet;
                switch (enTank.Item1.weapon)
                {
                    case WeaponType.DoubleBullet:
                        playerWeapon = Types.WeaponType.DoubleBullet;
                        break;

                }

                enSpawnedList.Add(new Tuple<Types.Tank, double>(GameState.CreateTankState(new FMath.Vector2(enTank.Item1.direction.X, enTank.Item1.direction.Y),
                                                                                           new FMath.Vector2(enTank.Item1.position.X, enTank.Item1.position.Y),
                                                                                           enTank.Item1.velocity,
                                                                                           enTank.Item1.wheelRoolTheta,
                                                                                           Types.createEnemyType(enType),
                                                                                           enTank.Item1.isStealth,
                                                                                           enBonus,
                                                                                           enWeapon), enTank.Item2));
            }
            #endregion


            //Caricamento blocchi
            Types.BlockMakeUp[,] blockMap = new Types.BlockMakeUp[13, 13];
            for (int i = 0; i < 13; ++i)
            {
                for (int j = 0; j < 13; ++j)
                {
                   Types.BlockMakeUp makeUp;
                   switch (blockGrid[i * 13 + j].Item1)
                   {
                       case BlockType.Steel:
                           bool[,] steelBrickArray = new bool[2,2];
                           for (int c = 0; c < 2; ++c)
                           {
                               for (int k = 0; k < 2; ++k)
                               {
                                   steelBrickArray[c, k] = blockGrid[i * 13 + j].Item2[c * 2 + k];
                               }
                           }
                           makeUp = Types.BlockMakeUp.NewSteelBrick(new Casanova.Variable<bool[,]>(steelBrickArray, steelBrickArray));
                           break;
                       case BlockType.Ceramic:
                           bool[,] ceramicBrickArray = new bool[4,4];
                           for (int c = 0; c < 4; ++c)
                           {
                               for (int k = 0; k < 4; ++k)
                               {
                                   ceramicBrickArray[c, k] = blockGrid[i * 13 + j].Item2[c * 4 + k];
                               }
                           }
                           makeUp = Types.BlockMakeUp.NewCeramicBrick(new Casanova.Variable<bool[,]>(ceramicBrickArray, ceramicBrickArray));
                           break;
                       case BlockType.Space:
                           makeUp = Types.BlockMakeUp.Space;
                           break;
                       case BlockType.Stealth:
                           makeUp = Types.BlockMakeUp.Stealth;
                           break;
                       default:
                           makeUp = Types.BlockMakeUp.Empty;
                           break;
                   }
                   blockMap[i, j] = makeUp;
                }
            }
           
            //caricamento bonus
            foreach (SerializableTuple<Bonus, Microsoft.Xna.Framework.Vector2, float> bonus in bonusList)
            {
                Types.Bonus bonusType = Types.Bonus.None;
                switch (bonus.Item1)
                {
                    case Bonus.Life:
                        bonusType = Types.Bonus.Life;
                        break;
                    case Bonus.Nuclear:
                        bonusType = Types.Bonus.Nuclear;
                        break;
                    case Bonus.Shield:
                        bonusType = Types.Bonus.Shield;
                        break;
                    case Bonus.WeaponUp:
                        bonusType = Types.Bonus.WeaponUp;
                        break;
                }

                bnList.Add(new Tuple<Types.Bonus, FMath.Vector2, double>(bonusType, new FMath.Vector2(bonus.Item2.X, bonus.Item2.Y), bonus.Item3));
            }
            

            GameState.gameState = GameState.loadGameState(playerTank, 
                                                          playerLives,
                                                          completedLevels,
                                                          plState, 
                                                          playerTransitionClock, 
                                                          generatedEnemies, 
                                                          destroyedEnemies, 
                                                          enDestroyedList, 
                                                          enSpawnedList, 
                                                          enList, 
                                                          bnList,
                                                          blockMap);
        }
    }
}
